#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <map>
using namespace std;

#define MAXLEN_DGRAM  (2047)

typedef unsigned char UCHAR;
typedef unsigned short USHORT;
typedef unsigned int  UINT;

#define NQ_TIMEOUT       (3600)
#define NQ_PT_ARP        (1)
#define NQ_PT_IP         (2)
#define SVRPORT_DNS      53
#define FLAG_TCP_SYN     0x02
#define FLAG_TCP_SYNACK  0x12
#define ISUNICAST(ip) ((0x0 != ip) && ((ip&0xFF) < 0xE0))
#define NQ_IPSTR(ip) (inet_ntoa(*((struct in_addr *)(&(ip)))))
#define NQ_ISDNS(port) (SVRPORT_DNS == ntohs(port))
#define NQ_TCPHDR_LEN(len) (4 * ((len & 0xf0) >> 4))
#define NQ_DNSCHAR(c) (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) ||\
                       ((c >= '0') && (c <= '9')) || ('-' == c))

#pragma pack(push)
#pragma pack(1)

/* ether header */
#define MAXLEN_ETHHDR (14)
typedef struct tagEthHdr 
{
    UCHAR  dmac[6];
    UCHAR  smac[6];
    USHORT type;
} ETHHDR_S;

/* ip header */
#define MAXLEN_IPHDR (20)
typedef struct tagIpHdr 
{
    UCHAR  ver;
    UCHAR  tos;
    USHORT total;
    USHORT ident;
    USHORT flag;
    UCHAR  ttl;
    UCHAR  proto;
    USHORT checksum;
    UINT   sip;
    UINT   dip;
} IPHDR_S;

/* udp header */
typedef struct tagUdpHdr
{
    USHORT  sport;
    USHORT  dport;
    USHORT  len;
    USHORT  checksum;
} UDPHDR_S;

/* tcp header */
typedef struct tagTcpHdr
{
    USHORT  sport;
    USHORT  dport;
    UINT    seq;
    UINT    ack;
    UCHAR   len;
    UCHAR   flag;
    USHORT  win;
    USHORT  checksum;
    USHORT  urp;
} TCPHDR_S;

/* icmp header */
typedef struct tagIcmpHdr
{
    UCHAR  type;
    UCHAR  code;
    USHORT checksum;
    USHORT id;
    USHORT seq;
    USHORT timestamp;
} ICMPHDR_S;

/* DNS hdr */
typedef struct tagDnsHdr
{
    USHORT tid;
    USHORT flag;
    USHORT question_cnt;
    USHORT answer_cnt;
    USHORT author_cnt;
    USHORT addit_cnt;
} DNSHDR_S;

/* DNS data */
typedef struct tagDnsData
{
    UCHAR flag;
    UCHAR offset;
    USHORT type;
    USHORT qclass;
    UINT ttl;
    USHORT data_len;    
} DNSDATA_S;

/* ARP hdr */
typedef struct tagARPHdr
{
    USHORT h_type;
    USHORT p_type;
    UCHAR  h_len;
    UCHAR  p_len;
    USHORT opt;
    UCHAR  smac[6];
    UINT   sip;
    UCHAR  dmac[6];
    UINT   dip;    
} ARPHDR_S;

#pragma pack(pop)

typedef struct tagNQSvr
{
    UINT ip;
    UINT port;

    bool operator <(const tagNQSvr& other) const
    {
        if (ip < other.ip)
        {
            return true;
        }
        else if (ip > other.ip)
        {
            return false;
        }
        else if (port < other.port)
        {
            return true;
        }
        else if (port > other.port)
        {
            return false;
        }
        
        return false;
    }
} NQSVR_S;

class NQDOMAIN
{
public:
    UINT ip;
    char name[256];

    bool operator <(const NQDOMAIN& other) const
    {
        if (ip < other.ip)
        {
            return true;
        }
        else if (ip > other.ip)
        {
            return false;
        }
        else if (strcmp(name, other.name) < 0)
        {
            return true;
        }
        else if (strcmp(name, other.name) > 0)
        {
            return false;
        }
        
        return false;
    }

    NQDOMAIN()
    {
        ip = 0;
        memset(name, 0, sizeof(name));
    }
};

typedef map<UINT, UINT> IPMAP;
typedef map<UINT, UINT>::iterator IPMAPITR;
typedef map<NQSVR_S, NQSVR_S> SVRMAP;
typedef map<NQSVR_S, NQSVR_S>::iterator SVRMAPITR;
typedef map<NQDOMAIN, NQDOMAIN> DOMAINMAP;
typedef map<NQDOMAIN, NQDOMAIN>::iterator DOMAINMAPITR;

#define __NQ_DEBUGGING__  0
#define DEBUG_OUT(...) \
    { \
    if (__NQ_DEBUGGING__) \
        printf(__VA_ARGS__); \
    }

